package designpattern.visitor.ast;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.stmt.IfStmt;
import com.github.javaparser.ast.stmt.Statement;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.WhileStmt;
import com.github.javaparser.ast.stmt.ForStmt;
import com.github.javaparser.ast.stmt.DoStmt;
import com.github.javaparser.ast.stmt.ForEachStmt;
import com.github.javaparser.ast.stmt.SwitchStmt;
import com.github.javaparser.ast.stmt.SynchronizedStmt;
import com.github.javaparser.ast.stmt.TryStmt;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

public class JavaAST {
    public static void main(String[] args) {
        String simpleClassSrc = "class SimpleClass{\n" + //
                "    public int testMethod(int param){\n" + //
                "        if(param < 0 ) return -1;\n" + //
                "        else return 1;\n" + //
                "\n" + //
                "    }\n" + //
                "    \n" + //
                "    public void printMessage(String message) {\n" + //
                "        System.out.println(\"Message: \" + message);\n" + //
                "    }\n" + //
                "    \n" + //
                "    private double calculateAverage(double[] numbers) {\n" + //
                "        double sum = 0;\n" + //
                "        for (double num : numbers) {\n" + //
                "            sum += num;\n" + //
                "        }\n" + //
                "        return numbers.length > 0 ? sum / numbers.length : 0;\n" + //
                "    }\n" + //
                "}";

        CompilationUnit parsed = StaticJavaParser.parse(simpleClassSrc);

        // 使用传统的方法在语法树上搜索
        for (TypeDeclaration<?> t : parsed.getTypes()) {
            for (Object m : t.getMembers()) {
                if (m instanceof MethodDeclaration) {
                    System.out.println(((MethodDeclaration) m).getName());
                }
            }
        }
        System.out.println();

        // 使用visitor模式,打印所有方法名
        parsed.accept(new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodDeclaration n, Void arg) {
                System.out.println(n.getName());
            }
        }, null);
        System.out.println();

        String nestedIfStatementSrc = "class NestedIfStatement{\n" + //
                "    public int testMethod(int param){\n" + //
                "        if(param < 0 ){\n" + //
                "            if(param < -1) return -1;\n" + //
                "        }\n" + //
                "        else return 1;\n" + //
                "        \n" + //
                "        // while循环中的if\n" + //
                "        int i = 0;\n" + //
                "        while(i < 10) {\n" + //
                "            if(i == 5) break;\n" + //
                "            i++;\n" + //
                "        }\n" + //
                "        \n" + //
                "        // for循环中的if\n" + //
                "        for(int j = 0; j < 5; j++) {\n" + //
                "            if(j % 2 == 0) {\n" + //
                "                System.out.println(\"Even\");\n" + //
                "            }\n" + //
                "        }\n" + //
                "        \n" + //
                "        // try-catch中的if\n" + //
                "        try {\n" + //
                "            if(param > 100) {\n" + //
                "                throw new Exception();\n" + //
                "            }\n" + //
                "        } catch(Exception e) {\n" + //
                "            if(e != null) {\n" + //
                "                System.out.println(\"Error\");\n" + //
                "            }\n" + //
                "        }\n" + //
                "    }\n" + //
                "}";
        CompilationUnit parsedNestedIfStatementSrc = StaticJavaParser.parse(nestedIfStatementSrc);

        System.out.println();

        // 使用visitor,打印所有if语句的条件
        parsedNestedIfStatementSrc.accept(new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(IfStmt n, Void arg) {
                System.out.println(n.getCondition());
                super.visit(n, arg);
            }

        }, null);
        System.out.println();
        
        // 使用新添加的传统方法打印所有if条件

        
        System.out.println("=== 使用传统方法打印所有if条件 ===");
        printAllIfConditionsTraditional(parsedNestedIfStatementSrc);
        System.out.println();
    }
    
    /**
     * 使用循环和递归的传统方法打印编译单元中所有if语句的条件
     * @param compilationUnit 要分析的编译单元
     */
    public static void printAllIfConditionsTraditional(CompilationUnit compilationUnit) {
        for (TypeDeclaration<?> type : compilationUnit.getTypes()) {
            for (Object member : type.getMembers()) {
                if (member instanceof MethodDeclaration) {
                    MethodDeclaration method = (MethodDeclaration) member;
                    // 搜索方法体中的if语句
                    searchIfStatementsInMethod(method);
                }
            }
        }
    }
    
    /**
     * 使用传统方法递归搜索方法中的if语句
     * @param method 要搜索的方法声明
     */
    private static void searchIfStatementsInMethod(MethodDeclaration method) {
        if (method.getBody().isPresent()) {
            BlockStmt body = method.getBody().get();
            for (Statement stmt : body.getStatements()) {
                // 对每个语句都进行递归搜索，而不仅仅是IfStmt
                searchIfStatementsInStatement(stmt);
            }
        }
    }
    
    /**
     * 递归搜索语句中的if语句
     * @param stmt 要搜索的语句
     */
    private static void searchIfStatementsInStatement(Statement stmt) {
        if (stmt instanceof IfStmt) {
            IfStmt ifStmt = (IfStmt) stmt;
            System.out.println("找到嵌套if条件: " + ifStmt.getCondition());
            searchIfStatementsInStatement(ifStmt.getThenStmt());
            if (ifStmt.getElseStmt().isPresent()) {
                searchIfStatementsInStatement(ifStmt.getElseStmt().get());
            }
        } else if (stmt instanceof BlockStmt) {
            BlockStmt block = (BlockStmt) stmt;
            for (Statement innerStmt : block.getStatements()) {
                searchIfStatementsInStatement(innerStmt);
            }
        } else if (stmt instanceof WhileStmt) {
            WhileStmt whileStmt = (WhileStmt) stmt;
            searchIfStatementsInStatement(whileStmt.getBody());
        } else if (stmt instanceof ForStmt) {
            ForStmt forStmt = (ForStmt) stmt;
            searchIfStatementsInStatement(forStmt.getBody());
        } else if (stmt instanceof DoStmt) {
            DoStmt doStmt = (DoStmt) stmt;
            searchIfStatementsInStatement(doStmt.getBody());
        } else if (stmt instanceof ForEachStmt) {
            ForEachStmt forEachStmt = (ForEachStmt) stmt;
            searchIfStatementsInStatement(forEachStmt.getBody());
        } else if (stmt instanceof SwitchStmt) {
            SwitchStmt switchStmt = (SwitchStmt) stmt;
            for (var entry : switchStmt.getEntries()) {
                // 遍历switch case中的所有语句
                for (Statement innerStmt : entry.getStatements()) {
                    searchIfStatementsInStatement(innerStmt);
                }
            }
        } else if (stmt instanceof SynchronizedStmt) {
            SynchronizedStmt syncStmt = (SynchronizedStmt) stmt;
            searchIfStatementsInStatement(syncStmt.getBody());
        } else if (stmt instanceof TryStmt) {
            TryStmt tryStmt = (TryStmt) stmt;
            searchIfStatementsInStatement(tryStmt.getTryBlock());
            for (var catchClause : tryStmt.getCatchClauses()) {
                searchIfStatementsInStatement(catchClause.getBody());
            }
            if (tryStmt.getFinallyBlock().isPresent()) {
                searchIfStatementsInStatement(tryStmt.getFinallyBlock().get());
            }
        }
    }
}